﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bingosoft.RestService.Attributes;
using Bingosoft.Data;
using MobileServer.Bll.Common;
using Newtonsoft.Json;
using Bingosoft.OAuth.Client.Token.Grant.Code;
using Bingosoft.OAuth.Client.SSO;
using Bingosoft.OAuth.Client;
using BingoSoft.Oauth.Client;
using System.Configuration;
using Bingosoft.Swimming.Core.Helper;
using NLog;

namespace MobileServer.Bll.Bis
{
    public enum UserLogType { 系统= 0,财务=1,活动=2,鄙视=3}
    public interface IUserService
    {
        bool SetSignIn(string ActivityUserId);

        void Robbed(string ActivityUserId, string FromUserId);

        void Despises(string FromUserId, string ToUserId);

        void SetEnter(string ActivityId, string UserId);
        void SetNotEnter(string ActivityId, string UserId);

        UserLogInfo[] GetUserLogs(string username);
    }

    [Service("UserService")]
    public class UserService : IUserService
    {
        private Dao dao = Dao.Get();
        private decimal ticketPrice = decimal.Parse(ConfigurationManager.AppSettings["TicketPrice"]);
        private ActivityService activityService = new ActivityService();

        Logger logger = LogManager.GetCurrentClassLogger();

        public UserService()
        {
            
        }

        /// <summary>
        ///签到后的业务逻辑如下：
        ///1.检查用户账户余额是否足够扣除相应票价。
        ///1.1.足够扣除时进行扣除操作
        ///1.1.1 扣除后将参加次数时行累加
        ///1.1.2 派发10张抢夺卡
        ///1.1.3 记录用户消费日志
        ///1.2 不足时提醒管理员需要充值
        ///2 将活动用户信息更新为已签到
        /// </summary>
        /// <param name="ActivityUserId"></param>
        /// <returns></returns>
        public virtual bool SetSignIn(string ActivityUserId)
        {
            ActivityUserInfo ActivityUser = GetActivityUserInfo(ActivityUserId);

            if (ActivityUser.SignIn)
                throw new BisException("已签过到了!");

            //UserInfo userInfo = GetUserInfo(au.UserID.ToString());

            //if (userInfo.Balance - ticketPrice < 0)
            //    throw new BisException("余额不足!");

            //int snatchCard = CreateSnatchCard(au); //派发抢夺卡
            //byte newRank = UpgroundRank(userInfo); //升级策略
            //int oldRnak = userInfo.Rank;

            //userInfo.Balance -= ticketPrice; //减票价
            //userInfo.AttendTimes++; //递增参加次数
            //userInfo.Consume += ticketPrice; //增加总消费额
            //userInfo.Rank = newRank;
            //userInfo.SnatchCard += snatchCard;

            ActivityInfo activity = activityService.GetActivityInfo(ActivityUser.ActivityID.ToString());

            //签到
            dao.ExecuteNonQuery("Activity.UpdateActivityUser", new { Id = ActivityUser.Id, SignIn = true, Robbed = 0 });// 签到
            //生成财务记录
            dao.ExecuteNonQuery("Balance.Insert", new
            {
                Id = Guid.NewGuid(),
                UserID = ActivityUser.UserID,
                ActivityId = ActivityUser.ActivityID,
                Amount = (double)(0 - activity.Tickte),
                @Type = 0
            });
            //SetSignInStatus(au, true);

            //dao.ExecuteNonQuery("Security.UpdateUser", userInfo); //更新用户信息
            //SignInLog(au, snatchCard, newRank, oldRnak);

            return true;
        }

        private void SetSignInStatus(ActivityUserInfo ActivityUser, bool signIn)
        {
        }


        private void SignInLog(ActivityUserInfo au, int snatchCard, byte newRank, int oldRnak)
        {

            UserLogInfo log = new UserLogInfo
            {
                ActivityID = au.ActivityID,
                Id = Guid.NewGuid(),
                LogType = (int)UserLogType.活动,
                UserID = au.UserID,
                Message = "成功签到，系统派发给" + snatchCard + "张掠夺卡"
            };
            dao.ExecuteNonQuery("User.UserLogs.Insert", log);

            log = new UserLogInfo
            {
                ActivityID = au.ActivityID,
                Id = Guid.NewGuid(),
                LogType = (int)UserLogType.财务,
                UserID = au.UserID,
                Message = "系统扣除活动费" + ticketPrice + "元"
            };
            dao.ExecuteNonQuery("User.UserLogs.Insert", log);

            if (oldRnak != newRank)
            {
                log = new UserLogInfo
                {
                    ActivityID = au.ActivityID,
                    Id = Guid.NewGuid(),
                    LogType = (int)UserLogType.系统,
                    UserID = au.UserID,
                    Message = "恭喜您升级了！"
                };
            }
            dao.ExecuteNonQuery("User.UserLogs.Insert", log);
        }

        public ActivityUserInfo GetActivityUserInfo(string ActivityUserId)
        {
            return dao.QueryEntity<ActivityUserInfo>("Activity.GetActivityUser", new { Id = ActivityUserId });
        }

        public ActivityUserInfo GetActivityUserInfo(string ActivityId, string UserId)
        {
            return dao.QueryEntity<ActivityUserInfo>("Activity.GetActivityUser", new { ActivityId = ActivityId, UserId = UserId });
        }

        [ServiceMethod]
        public UserInfo GetUserInfo(string UserId)
        {
            return dao.QueryEntity<UserInfo>("Security.Get", new { Id = UserId });
        }

        [ServiceMethod]
        public ViewModel<UserInfo> GetUserByLoginId(string loginId)
        {
            return new ViewModel<UserInfo>(200, "", dao.QueryEntity<UserInfo>("Security.GetUserLoginInfo", new { LoginId = loginId }));
        }

        /// <summary>
        /// 创建掠夺卡策略
        /// </summary>
        /// <returns></returns>
        protected virtual int CreateSnatchCard(ActivityUserInfo userInfo)
        {
            return 10;
        }

        /// <summary>
        /// 升级策略
        /// </summary>
        /// <param name="userInfo"></param>
        /// <returns></returns>
        protected virtual byte UpgroundRank(UserInfo userInfo)
        {
            /*升级策略：
             * 根据参加次数升级
             * 参加一次为1级，两次为2级，四次为3级，五次为
             */
            return (byte)(userInfo.AttendTimes + 1);
        }
        /// <summary>
        /// 初始化被抢次数
        /// </summary>
        /// <returns></returns>
        private int GetDefaultRobbed()
        {
            return 5;
        }

        /// <summary>
        /// 将会员设为已报名逻辑如下：
        /// 检查会员账号里的钱是否足够抵扣票价，不足时不给报名。
        /// </summary>
        /// <param name="ActivityUserId"></param>
        public virtual void SetEnter(string ActivityId, string UserId)
        {
            Guid id = Guid.NewGuid();
            string code = Math.Abs(Guid.NewGuid().GetHashCode()).ToString().PadLeft(10, '0');
            int ret = dao.ExecuteNonQuery("ActivityUser.Insert", new { Id = id, ActivityID = ActivityId, UserID = UserId, Code = code });
            ActivityInfo activity = activityService.GetActivityInfo(ActivityId);
            if (activity.IsSMS && ret > 0)
            {
                //报名成功后将活动随机码给用户发送验证码
                SendActivityCodeToUser(UserId, ActivityId, code);
                //更新SMS发送记录
                dao.ExecuteNonQuery("Activity.UpdateActivityUserSMS", new { Id = id });
            }
            
            //分发消息给所有会员。*待讨论
            
        }

        private void SendActivityCodeToUser(string userId, string activityId, string code)
        {
            UserInfo user = GetUserInfo(userId);
            ActivityInfo activity = activityService.GetActivityInfo(activityId);
            string startDate = DateTime.Parse(activity.StartDate).ToShortDateString();
            string msg = "尊贵的游泳协会会员{0}，您成功报名了{1}的活动，验证码：{2}。到场后请出示该验证码并报出品高软件即可入场，感谢您对本活动的支持！";
            msg = string.Format(msg, user.Name, startDate, code);

            //发送邮件
            if (!string.IsNullOrEmpty(user.Email))
            {
                System.Threading.ThreadPool.QueueUserWorkItem(o =>
                {
                    EmailHelper.Send("xupeng@gz-mstc.com", user.Email, "游泳协会活动确认函", msg);
                });
            }

            //发送短信
            if (!string.IsNullOrEmpty(user.MobilePhone))
            {
                System.Threading.ThreadPool.QueueUserWorkItem(o =>
                {
                    SmsHelper.Send(user.MobilePhone, msg);
                });
            }
        }

        public void SetNotEnter(string ActivityId, string UserId)
        {
            dao.ExecuteNonQuery("ActivityUser.Cancel", new { ActivityId = ActivityId, UserId = UserId });
            //撤销报名功能
            //SetEnterStatus(GetActivityUserInfo(ActivityId, UserId).Id.ToString(), false);
        }

        private void SetEnterStatus(string ActivityUserId, bool enter)
        {
            dao.ExecuteNonQuery("Activity.UpdateActivityUser", new { Id = ActivityUserId, IsEnter = enter });
        }

        /// <summary>
        /// 检查被抢人被抢次数是否小于5，大于等于5时不再让人抢它。
        /// 检查是还有抢夺卡
        /// 检查被抢人是否已经被抢夺人抢过了
        /// 将被抢用户的被抢次数增加1
        /// 减掉抢掠用户的抢夺卡张数
        /// 根据策略得到被抢值
        /// 从被抢人账户减掉该值
        /// 抢夺人增加该值
        /// 增加一条抢夺记录
        /// 为抢的和被抢的都增加一条日志
        /// </summary>
        /// <param name="ActivityUserId"></param>
        /// <param name="FromUserId"></param>
        public void Robbed(string ActivityUserId, string FromUserId)
        {
            ActivityUserInfo au = GetActivityUserInfo(ActivityUserId);
            UserInfo fromUserInfo = GetUserInfo(FromUserId);
            UserInfo toUserInfo = GetUserInfo(au.UserID.ToString());

            if (fromUserInfo.SnatchCard == 0)
                throw new BisException("您已经没有抢夺卡了！");

            if (au.Robbed >= 5)
                throw new BisException("TA的被抢次数达到上限，换个人抢吧！");

            if (dao.QueryScalar<int>("Activity.RobRecordInfo.Exist", new { ActivityID = au.ActivityID, FromUserID = fromUserInfo.Id, ToUserID = toUserInfo.Id }) > 0)
                throw new BisException("您已经抢过" + toUserInfo.Name + "了，换个试试！");

            au.Robbed++;
            fromUserInfo.SnatchCard--;
            decimal rebbedAmount = GetRebbedAmount(fromUserInfo, toUserInfo);
            toUserInfo.Balance -= rebbedAmount;
            
            if (toUserInfo.Balance < 0)
                throw new BisException(toUserInfo.Name + "的余额不够你抢啦，换个人试试");

            fromUserInfo.Balance += rebbedAmount;

            dao.ExecuteNonQuery("Activity.UpdateActivityUser", au);
            dao.ExecuteNonQuery("Security.UpdateUser", fromUserInfo);
            dao.ExecuteNonQuery("Security.UpdateUser", toUserInfo);

            var robRecord = new RobRecordInfo { ActivityID = au.ActivityID, Amount = rebbedAmount, FromUserID = fromUserInfo.Id, ToUserID = toUserInfo.Id, Id = Guid.NewGuid(), UpdateTime = DateTime.Now };
            dao.ExecuteNonQuery("Activity.RobRecordInfo.Inert", robRecord);

            dao.ExecuteNonQuery("User.UserLogs.Insert", new UserLogInfo { ActivityID = au.ActivityID, Id = Guid.NewGuid(), LogType = (byte)UserLogType.财务, Message = "被" + fromUserInfo.Name + "抢了" + rebbedAmount + "元", UserID = toUserInfo.Id, UpdateTime = DateTime.Now });
            dao.ExecuteNonQuery("User.UserLogs.Insert", new UserLogInfo { ActivityID = au.ActivityID, Id = Guid.NewGuid(), LogType = (byte)UserLogType.财务, Message = "抢了" + toUserInfo.Name + rebbedAmount + "元", UserID = fromUserInfo.Id, UpdateTime = DateTime.Now });
        }

        private decimal GetRebbedAmount(UserInfo fromUserInfo, UserInfo toUserInfo)
        {
            return 0.5M;
        }


        public void Despises(string FromUserId, string ToUserId)
        {
            UserInfo fromUserInfo = GetUserInfo(FromUserId);
            UserInfo toUserInfo = GetUserInfo(ToUserId);
            UserLogInfo log = new UserLogInfo
            {
                ActivityID = Guid.Empty,
                Id = Guid.NewGuid(),
                LogType = (int)UserLogType.鄙视,
                UserID = new Guid(ToUserId),
                Message = fromUserInfo.Name + "鄙视你不参加协会活动！"
            };
            dao.ExecuteNonQuery("User.UserLogs.Insert", log);


            log = new UserLogInfo
            {
                ActivityID = Guid.Empty,
                Id = Guid.NewGuid(),
                LogType = (int)UserLogType.鄙视,
                UserID = new Guid(FromUserId),
                Message = "您成功鄙视了" + toUserInfo.Name + "不参加协会活动！"
            };
            dao.ExecuteNonQuery("User.UserLogs.Insert", log);
        }


        public UserLogInfo[] GetUserLogs(string username)
        {
            return dao.QueryEntities<UserLogInfo>("User.UserLogs.FindByUserName", new { UserName = username }).ToArray();
        }
    }
}
